<template>
    <el-select
        ref="selectScrollRef"
        v-model="selectValue"
        :style="`width: ${width}`"
        :multiple="multiple"
        :disabled="disabled"
        :no-data-text="noDataText"
        :loading-text="loadingText"
        filterable
        remote
        :remote-method="remoteMethod"
        :popper-class="popperClass"
        remote-show-suffix
        clearable
        :options="options"
        :loading="loading"
        :placeholder="placeholder"
        @visible-change="visibleChangeHandle"
        @clear="clearHandle"
        @change="changeHandle">
        <div
            v-infinite-scroll="queryData"
            :infinite-scroll-immediate="false"
            :infinite-scroll-disabled="infiniteScrollDisabled"
            style="max-height: 200px">
            <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value">
                <span>{{ item.label }}</span>
            </el-option>
        </div>
    </el-select>
</template>

<script setup lang="ts">
import { ref, watch, getCurrentInstance, computed } from 'vue';
import { ElSelect } from 'element-plus';
import { queryIndustryList, queryBankList } from '../api/ZwUnityKitSelect';
// import { PropsType, EmitType, ListItem } from './type';

defineOptions({
    name: 'ZwUnityKitSelect'
});

interface PropsType {
    /**
     * v-model绑定值，选中的数据，默认为空，回显时传递对应的id值
     * 单选时为string 多选时为string数组
     */
    modelValue: string | string[];
    /** 是否多选，默认为单选 */
    multiple?: boolean;
    /** 下拉框宽度，默认为360px */
    width?: string;
    /**
     * 回显时传递的options
     * 注意，里面的对象必须包含value和label，value为对应的id，label为显示名称
     */
    option?: Array<any>;
    /**
     * 下拉选择类型，默认为accountInfo
     * 为空时，为常规select组件，可通过传递option选择下拉
     * 若传此参数，则option自动失效
     * profession 所属行业（暂不支持）
     * accountInfo 对公账号开户行信息
     */
    selectType?: string;
    /** placeholder */
    placeholder?: string;
    /** 是否禁用 */
    disabled?: boolean;
}

interface EmitType {
    /**
     * modelValue数据双向绑定，单选时为string，多选时为数组类型的string
     */
    (e: 'update:modelValue', url: string | string[]): void;
    /**
     * 选中change事件，回传选中的数据，单选时为对象类型，多选时为数组类型
     */
    (e: 'change', val: any | any[]): void;
}

interface ListItem {
    value: string;
    label: string;
}

const props = withDefaults(defineProps<PropsType>(), {
    modelValue: '',
    multiple: false,
    width: '360px',
    option: () => [],
    selectType: 'accountInfo',
    placeholder: '',
    disabled: false
});

const emit = defineEmits<EmitType>();

const app = getCurrentInstance();
const selectScrollRef = ref();
const noDataText = ref<string>('暂无数据');
const loadingText = ref<string>('加载中..');
const selectValue = ref<string | string[]>();
const options = ref<ListItem[]>([]);
const loading = ref<boolean>(false);
const page = ref<number>(0);
const page_size = ref<number>(20);
const keywords = ref<string>('');
const infiniteScrollDisabled = ref<boolean>(false);
const popperClass = ref<string>(`select_poper_class_${Math.random().toString(36).substring(2)}`);

/**
 * @description: clear 事件
 * @return {*}
 */
const clearHandle = () => {
    page.value = 0;
    keywords.value = '';
    options.value.splice(0);
    selectScrollRef.value.focus();
};

/**
 * @description: visibleChange 事件
 * @param {*} val
 * @return {*}
 */
const visibleChangeHandle = async flag => {
    if (flag) {
        page.value = 0;
        keywords.value = '';
        options.value.splice(0);
        await queryData();
    }
};

/**
 * @description: change事件
 * @param {*} val
 * @return {*}
 */
const changeHandle = val => {
    emit('update:modelValue', val);
    if (props.multiple) {
        emit(
            'change',
            options.value.filter(({ value }) => val.includes(value))
        );
    } else {
        emit(
            'change',
            options.value.find(({ value }) => val === value)
        );
    }
};

/**
 * @description: 远程搜索
 * @param {*} query
 * @return {*}
 */
const remoteMethod = async (query: string) => {
    if (query !== '') {
        loading.value = true;
        await queryData(query);
        loading.value = false;
    } else {
        options.value = [];
    }
};

/**
 * @description: 根据类型搜索 profession 行业  accountInfo 开户行
 * @param {*} keywords
 * @return {*}
 */
const queryData = async (keywords?: string) => {
    switch (props.selectType) {
        case 'profession':
            await getProfessionData(keywords);
            break;
        case 'accountInfo':
            await getAccountInfoData(keywords);
            break;
    }
};

/**
 * @description: 行业
 * @param {*} keywords
 * @return {*}
 */
const getProfessionData = async (keywords?: string) => {
    const res = await queryIndustryList(app, { keywords });
};

/**
 * @description: 开户行
 * @param {*} keywords
 * @return {*}
 */
const getAccountInfoData = async (keywords_?: string) => {
    if (keywords_) {
        if (keywords.value != keywords_) {
            page.value = 0;
            infiniteScrollDisabled.value = false;
            keywords.value = keywords_;
            options.value.splice(0);
            const popDom = document.querySelector(`.${popperClass.value}`) as HTMLElement;
            const scrollDom = popDom.querySelector('.el-scrollbar__wrap') as HTMLElement;
            scrollDom.scrollTop = 0;
        }
    }
    page.value++;
    const params = {
        page: page.value,
        page_size: page_size.value,
        keywords: keywords.value
    };
    const res = await queryBankList(app, params);
    if (res.code === 0) {
        if (res.data.total_page === page.value) {
            infiniteScrollDisabled.value = true;
        }
        const newArr = res.data.data.map(item => {
            const value = item.interbank_number;
            const label = item.full_name;
            return { value, label };
        });

        options.value.push(...newArr);
    }
};

watch(
    () => props.option,
    () => {
        if (props.option.length && props.modelValue.length) {
            selectValue.value = props.modelValue;
            options.value = props.option;
        }
    },
    { immediate: true, deep: true }
);
</script>

<style lang="scss" scoped>
@import './Index';
</style>
